#include "ns3/assert.h"
#include "ns3/log.h"
#include "ns3/header.h"
#include "ns3/simulator.h"
#include "infoTableHeader.h"
#include <vector>

NS_LOG_COMPONENT_DEFINE ("InfoTableHeader");

namespace ns3 {


NS_OBJECT_ENSURE_REGISTERED (InfoTableHeader);
InfoTableHeader::InfoTableHeader()
{
NS_LOG_FUNCTION (this);
}


InfoTableHeader::InfoTableHeader (std::vector<std::string> listF, std::vector<BasicChannel> fi,uint64_t fiBT,uint8_t bat):listOfFiles(listF), frameInformation(fi),frameInfBegTime(fiBT),battery(bat)
{
  NS_LOG_FUNCTION (this);
}

std::vector<std::string> InfoTableHeader::GetData(std::vector<BasicChannel> &fi,uint64_t &fiBT,uint8_t &bat)
{
    fi=frameInformation;
    fiBT=frameInfBegTime;
    bat=battery;

return listOfFiles;
}

TypeId
InfoTableHeader::GetTypeId (void)
{
  static TypeId tid = TypeId ("ns3::InfoTableHeader")
    .SetParent<Trailer> ()
    .AddConstructor<InfoTableHeader> ()
  ;
  return tid;   
}
TypeId
InfoTableHeader::GetInstanceTypeId (void) const
{
  return GetTypeId ();
}
void
InfoTableHeader::Print (std::ostream &os) const
{
  NS_LOG_FUNCTION (this << &os);
}
    
    
uint32_t
InfoTableHeader::GetSerializedSize (void) const
{
  NS_LOG_FUNCTION (this);
  uint32_t size=0;
 for(uint32_t i=0;i<listOfFiles.size();i++)
  {      size+=2;
         size+=(listOfFiles[i]).length();
  }
    uint32_t ret=8+2+2+2+size+(frameInformation.size()*(4+1+4));

return ret;
}

void
InfoTableHeader::Serialize (Buffer::Iterator start) const
{
  NS_LOG_FUNCTION (this << &start);
Buffer::Iterator j = start;
j.Prev(GetSerializedSize());

// Invia info frame information size
    
    j.WriteU16(frameInformation.size());
    
    j.WriteU64(frameInfBegTime);
    
    j.WriteU16(battery);
        
    
    
    /* Serialize the List of files owned by the node */
    j.WriteU16(listOfFiles.size());

for(unsigned k=0;k<listOfFiles.size();k++)
 { 
    j.WriteU16(listOfFiles[k].length());

   for ( unsigned i=0; i<listOfFiles[k].length(); i++) 
   {
     
     j.WriteU8((uint8_t)(listOfFiles[k].at(i)));
    
    }
  }
    
   /* Serialize the frame information */
    
    for(uint32_t i=0;i<frameInformation.size();i++)
    {
        j.WriteHtonU32 (frameInformation[i].node_name);
        j.WriteU8(frameInformation[i].free);
        j.WriteU32 (frameInformation[i].duration.ToDouble(Time::S));
        
    }
    
  
}



uint32_t
InfoTableHeader::Deserialize (Buffer::Iterator start)
{
  NS_LOG_FUNCTION (this << &start);

  Buffer::Iterator j = start;
   while(!j.IsStart())
   {
        j.Prev();
    }

        frameInformationSize=j.ReadU16();
    frameInfBegTime=j.ReadU64();
    battery=j.ReadU16();


uint16_t listOfFileSize=j.ReadU16();

    for ( uint16_t k=0; k<listOfFileSize; k++)
    {
        uint16_t length=j.ReadU16();
        std::string str;
        for(uint16_t i=0;i<length;i++)
            {
                str+=(char)j.ReadU8();
            }
                listOfFiles.push_back(str);

    }
    int node_n;
    bool status;
    uint32_t time;

    for(uint16_t i=0;i<frameInformationSize;i++)
    {
        
         node_n=j.ReadNtohU32 ();
        status=j.ReadU8();
        time=j.ReadU32 ();
        frameInformation.push_back(BasicChannel(node_n,status,Seconds(time)));
    }
    

  return GetSerializedSize ();
}

} // namespace ns3
